#include "head.h"
#include <l8w8jwt/encode.h>

int main(){
    //读取配置文件
    char sql_owner[100] = { 0 };//这个是存所有者“root”的
    char sql_password[100] = { 0 };
    char sql_name[100] = { 0 };//这个是库名称， “netDisk”
    char ip[100] = { 0 };
    char port[100] = { 0 };

    getparameter("sql_owner", sql_owner);
    getparameter("sql_password", sql_password);
    getparameter("sql_name", sql_name);
    getparameter("ip", ip);
    getparameter("port", port);
    //初始化数据库
    MYSQL *conn;
    conn = mysql_init(NULL);
    if (!mysql_real_connect(conn, NULL, sql_owner, sql_password, sql_name, 0, NULL, 0)){
        printf( "%s\n", mysql_error(conn));
        exit(1);
    }
    mysql_set_character_set(conn, "utf8");

    // 初始化线程池
    pool_t pool;
    init_pool(&pool, 3);
    // 初始化连接
    int socket_fd;
    init_tcp(&socket_fd, ip, port);

    // 监听用户连接
    int epoll_fd = epoll_create(1);
    // 放入监听
    add_epoll(epoll_fd, socket_fd);

    //定义一个存储用户信息的数组
    client_data *users = (client_data *)calloc(MAX_CONNECT, sizeof(client_data));
    int connect_num = 0;
    //初始化集合数组
    Set* set_list[30];
    init_set_list(set_list, 30);
    int time_last = time(NULL)%30;

    while(1){
        //就绪集合
        struct epoll_event ready[1024];
        int epoll_num=epoll_wait(epoll_fd,ready,1024,1000);
        //获得现在的时间标记
        int time_now = time(NULL) % 30; 
        //如果是第一个从上一秒进入这一秒的循环
        if(time_now != time_last){
            time_last = time_now;
            //踢出超时的客户端：将这个时间标记代表的集合中的连接全部踢出              
            //因为程序运行到这里已经经过了30s，此时还在这个集合内的连接都是30s未活跃的
            //如果连接有过请求，则这个连接肯定已经从这个集合出去，然后进入了其它集合
            for(int k = 0; k < set_list[time_now]->size; k++){
                //将集合中的元素全部移除
                int close_fd = remove_an_element(set_list[time_now]);
                //取消监听
                epoll_ctl(epoll_fd, EPOLL_CTL_DEL, close_fd, NULL);
                for(int q = 0; q < connect_num; q++){
                    if(users[q].net_fd == close_fd){
                        printf("用户 %s 无操作，已被踢出！\n", users[q].uname);
                        for(int l=q; l<connect_num; l++){
                            users[l] = users[l+1];
                        }
                    break;
                    }    
                break;
                }           
                //关闭连接
                close(close_fd);
                break;
            }
        }


        for(int i=0;i<epoll_num;i++){
            if(ready[i].data.fd==socket_fd){
                //获取新连接
                int net_fd=accept(socket_fd,NULL,NULL);
                add_epoll(epoll_fd, net_fd);
                users[connect_num].net_fd = net_fd;
                users[connect_num].tag_active = time(NULL)%30;
                connect_num++;
                add_element(set_list[time_now], net_fd);

            }else{
                for(int j = 0; j < connect_num; j++){
                    if(ready[i].data.fd != users[j].net_fd){
                        continue;
                    }
                    int net_fd = ready[i].data.fd;
                    //将这个连接从一个集合移到另一个集合
                    remove_element(set_list[users[j].tag_active], net_fd);
                    users[j].tag_active = time_now;
                    add_element(set_list[time_now], net_fd);

                    int type = -1;

                    int ret=recv(users[j].net_fd, &type,sizeof(int),0);
                    // printf("type = %d\n", type);


                    if(ret==0){
                        printf("用户%s断开链接\n", users[j].uname);
                        close(users[j].net_fd);
                        epoll_ctl(epoll_fd, EPOLL_CTL_DEL, net_fd, NULL);
                        for(int k = j; k < connect_num; k++){
                            users[j] = users[j+1];
                        }
                        j--;
                    }
                    switch(type){
                    case 0: //登录，注册                                               
                        {   int flag_break = 0;
                            //判断客户端能否登录
                            login_check(users[j].net_fd, &flag_break, users[j].uname);

                            char str[300] = {0};
                            //登录后加入用户数组
                            encode(users[j].uname, users[j].token, str);
                            memcpy(users[j].token, str, strlen(str));
                            strcpy(users[j].cur_path ,"/");
                            send(users[j].net_fd, users[j].token, strlen(users[j].token), 0);
                            //printf("sned num :%d\n token :%s\n", num, users[j].token);
                            break;
                        }
                    case 1://接收token
                        {   char buf[255]={0};
                            recv(users[j].net_fd, buf, sizeof(buf), 0);
                            //TODO解密出name
                            
                            bzero(buf,sizeof(buf));
                            decode(users[j].uname, users[j].token, buf);
                            strcpy(users[j].uname, buf);
                            printf("re_name:%s\n", users[j].uname);
                            
                            //接收当前路径
                            bzero(buf,sizeof(buf));
                            recv(users[j].net_fd,buf,sizeof(buf),0);
                            strcpy(users[j].cur_path,buf);

                            break;
                        }
                    case 2://长指令
                        deal_longcmd(pool,users[j].net_fd);     
                        break;

                    case 3://短指令
                        deal_short_cmd(users[j].net_fd, conn,users[j].uname, users[j].cur_path, users[j].last_deleted_file, users[j].last_deleted_path);
                        break;
                    }
                }
            }
        }
    }
}
